Ejemplo de análisis con pandas, geopandas y folium

Se presenta un ejemplo de análisis reproducible de datos geoespaciales: la distribución de especies de murciélagos en áreas silvestres protegidas (ASP) de Costa Rica.

Las salidas se presentan en tres formatos:

  • Tabular

  • Gráfica

  • Geoespacial

El ćodigo fuente de este ejercicio está disponible en https://github.com/pf3311-cienciadatosgeoespaciales/2021-iii/blob/main/contenido/b/ejemplo-analisis-pandas-geopandas-folium.ipynb y las salidas puede ser visualizadas en https://nbviewer.org/github/pf3311-cienciadatosgeoespaciales/2021-iii/blob/main/contenido/b/ejemplo-analisis-pandas-geopandas-folium.ipynb.

Entradas

Registros de presencia de murciélagos

Provienen de una consulta al portal de la Infraestructura Mundial de Información en Biodiversidad (GBIF).

Para efectos de este análisis, están disponibles en https://raw.githubusercontent.com/pf3311-cienciadatosgeoespaciales/2021-iii/main/contenido/b/datos/murcielagos.csv.

Procesamiento

import math

import pandas as pd

import matplotlib.pyplot as plt
%matplotlib inline

import geopandas as gpd

import folium
from folium import Marker
from folium.plugins import MarkerCluster
from folium.plugins import HeatMap

Lectura de datos

Registros de presencia de murciélagos

# Carga de registros de presencia de murciélagos en un dataframe de pandas

murcielagos = pd.read_csv("https://raw.githubusercontent.com/pf3311-cienciadatosgeoespaciales/2021-iii/main/contenido/b/datos/murcielagos.csv", 
                          sep="\t")

murcielagos
gbifID datasetKey occurrenceID kingdom phylum class order family genus species ... identifiedBy dateIdentified license rightsHolder recordedBy typeStatus establishmentMeans lastInterpreted mediaType issue
0 3416142999 50c9509d-22c7-4a22-a47d-8c48425ef4a7 https://www.inaturalist.org/observations/10118... Animalia Chordata Mammalia Chiroptera Vespertilionidae Rhogeessa Rhogeessa io ... Yuzefovich Alexander 2021-11-15T14:33:49 CC_BY_NC_4_0 jo22nfrog jo22nfrog NaN NaN 2021-12-08T05:34:32.772Z StillImage COORDINATE_ROUNDED
1 3416092578 50c9509d-22c7-4a22-a47d-8c48425ef4a7 https://www.inaturalist.org/observations/10131... Animalia Chordata Mammalia Chiroptera Phyllostomidae Uroderma Uroderma bilobatum ... Merav Vonshak 2021-11-17T06:37:32 CC_BY_NC_4_0 Merav Vonshak Merav Vonshak NaN NaN 2021-12-08T06:09:54.326Z StillImage COORDINATE_ROUNDED
2 3415771696 50c9509d-22c7-4a22-a47d-8c48425ef4a7 https://www.inaturalist.org/observations/88766024 Animalia Chordata Mammalia Chiroptera Phyllostomidae Artibeus Artibeus jamaicensis ... Yuzefovich Alexander 2021-07-27T06:38:03 CC_BY_NC_4_0 Alex Castelein Alex Castelein NaN NaN 2021-12-08T05:05:13.398Z StillImage COORDINATE_ROUNDED
3 3415765386 50c9509d-22c7-4a22-a47d-8c48425ef4a7 https://www.inaturalist.org/observations/36722404 Animalia Chordata Mammalia Chiroptera Phyllostomidae Uroderma Uroderma bilobatum ... Jay 2019-12-17T22:12:20 CC_BY_NC_4_0 Jay Jay NaN NaN 2021-12-08T04:59:02.428Z StillImage COORDINATE_ROUNDED
4 3415753400 50c9509d-22c7-4a22-a47d-8c48425ef4a7 https://www.inaturalist.org/observations/39440952 Animalia Chordata Mammalia Chiroptera Emballonuridae Rhynchonycteris Rhynchonycteris naso ... Jakob Fahr 2020-03-02T08:06:42 CC_BY_NC_4_0 Ben Zerante Ben Zerante NaN NaN 2021-12-08T05:48:47.800Z StillImage COORDINATE_ROUNDED
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
13184 45849434 847e2306-f762-11e1-a439-00145eb45e9a urn:catalog:LSUMZ:Mammals:12726 Animalia Chordata Mammalia Chiroptera Phyllostomidae Anoura Anoura geoffroyi ... NaN NaN CC0_1_0 NaN Gardner, Alfred L. NaN NATIVE 2021-12-02T03:54:15.435Z NaN INSTITUTION_COLLECTION_MISMATCH
13185 45849433 847e2306-f762-11e1-a439-00145eb45e9a urn:catalog:LSUMZ:Mammals:12725 Animalia Chordata Mammalia Chiroptera Phyllostomidae Anoura Anoura geoffroyi ... NaN NaN CC0_1_0 NaN Gardner, Alfred L. NaN NATIVE 2021-12-02T03:54:15.435Z NaN INSTITUTION_COLLECTION_MISMATCH
13186 45849432 847e2306-f762-11e1-a439-00145eb45e9a urn:catalog:LSUMZ:Mammals:12724 Animalia Chordata Mammalia Chiroptera Phyllostomidae Anoura Anoura geoffroyi ... NaN NaN CC0_1_0 NaN Gardner, Alfred L. NaN NATIVE 2021-12-02T03:54:15.437Z NaN INSTITUTION_COLLECTION_MISMATCH
13187 45849431 847e2306-f762-11e1-a439-00145eb45e9a urn:catalog:LSUMZ:Mammals:12723 Animalia Chordata Mammalia Chiroptera Phyllostomidae Anoura Anoura geoffroyi ... NaN NaN CC0_1_0 NaN Gardner, Alfred L. NaN NATIVE 2021-12-02T03:54:15.436Z NaN INSTITUTION_COLLECTION_MISMATCH
13188 45849415 847e2306-f762-11e1-a439-00145eb45e9a urn:catalog:LSUMZ:Mammals:10637 Animalia Chordata Mammalia Chiroptera Phyllostomidae Anoura Anoura geoffroyi ... NaN NaN CC0_1_0 NaN Arnold, Keith A. NaN NATIVE 2021-12-02T03:54:15.457Z NaN COORDINATE_REPROJECTED;INSTITUTION_COLLECTION_...

13189 rows × 50 columns

Polígonos de ASP

# Carga de registros de presencia de murciélagos en un dataframe de pandas

asp = gpd.read_file("https://github.com/pf3311-cienciadatosgeoespaciales/2021-iii/raw/main/contenido/b/datos/asp.geojson")

asp
id codigo nombre_asp cat_manejo estatus siglas_cat nombre_ac siglas_ac descripcio a_creacion n_creacion normativa area area_km version geometry
0 areas_silvestres_protegidas.1 A01 Montes Submarinos Area Marina de Manejo Estatal AMM Marina Cocos ACMC Area Marina de Manejo 2011 DE_36452 None 9.592623e+09 9.592623e+07 2019-11-19-001 POLYGON ((-87.00000 6.13333, -86.43333 5.73333...
1 areas_silvestres_protegidas.2 A02 Cabo Blanco Area Marina de Manejo Estatal AMM Area de Conservacion Tempisque ACT Area Marina de Manejo 1963 Ley_10 None 8.247806e+08 8.247806e+06 2019-11-19-001 POLYGON ((-85.14336 9.59649, -85.14332 9.59643...
2 areas_silvestres_protegidas.3 B01 Alberto Manuel Brenes Reserva Biologica Estatal RB Area de Conservacion Central ACC Area terrestre protegida 1993 Ley_7354 None 7.800440e+07 7.800440e+05 2019-11-19-001 POLYGON ((-84.63388 10.18202, -84.64167 10.177...
3 areas_silvestres_protegidas.4 B03 Isla Guayabo Reserva Biologica Estatal RB Area de Conservacion Tempisque ACT Isla 1973 DE_2858_A None 6.268092e+04 6.268092e+02 2019-11-19-001 POLYGON ((-84.87710 9.91109, -84.87737 9.91086...
4 areas_silvestres_protegidas.5 B04 Isla Pajaros Reserva Biologica Estatal RB Area de Conservacion Pacifico Central ACOPAC Isla 1976 DE_ 5963_A None 3.211583e+04 3.211583e+02 2019-11-19-001 POLYGON ((-84.99674 10.09266, -84.99696 10.092...
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
167 areas_silvestres_protegidas.168 Z31 Quebrada Rosario Zona Protectora Estatal ZP Area de Conservacion Central ACC Area terrestre protegida 1997 DE_ 26297_MINAE None 4.292695e+05 4.292695e+03 2019-11-19-001 POLYGON ((-84.07619 9.70425, -84.07689 9.70374...
168 areas_silvestres_protegidas.169 P10 Santa Rosa Parque Nacional Estatal PN Area de Conservacion Guanacaste ACG Isla 1966 Ley_3694 None 3.230258e+06 3.230258e+04 2019-11-19-001 MULTIPOLYGON (((-85.87565 10.84304, -85.87571 ...
169 areas_silvestres_protegidas.170 V25 Bahia Junquillal Refugio Nacional de Vida Silvestre Estatal RVS Area de Conservacion Guanacaste ACG Isla 1995 DE_ 23867_MIRENEM None 1.836792e+05 1.836792e+03 2021-08-20-001 MULTIPOLYGON (((-85.73360 10.95775, -85.73329 ...
170 areas_silvestres_protegidas.171 P18 Internacional La Amistad Parque Nacional Estatal PN Area de Conservacion La Amistad Pacifico ACLAP Area terrestre protegida 1982 DE_13324_A None 1.982896e+09 1.982896e+07 2019-11-19-001 MULTIPOLYGON (((-82.85282 9.01273, -82.85414 9...
171 areas_silvestres_protegidas.172 B09 Bicentenario de la República - Pájaro Campana Reserva Biologica Estatal RB Area de Conservacion La Amistad Pacifico ACLAP Area terrestre protegida 2021 DE_42615_MINAE None 5.082743e+07 5.082743e+05 2021-08-21-001 POLYGON ((-82.77351 8.94507, -82.81050 8.95856...

172 rows × 16 columns

Visualización preliminar

Mapa interactivo de puntos agrupados (clusters)

# Creación del mapa base
m = folium.Map(location=[9.6, -84.2], tiles='CartoDB positron', zoom_start=8)


# Capa de ASP
folium.GeoJson(data="https://github.com/pf3311-cienciadatosgeoespaciales/2021-iii/raw/main/contenido/b/datos/asp.geojson", 
               name="ASP").add_to(m)


# Capa de registros de presencia de murciélagos agrupados
mc = MarkerCluster()
for idx, row in murcielagos.iterrows():
    if not math.isnan(row['decimalLongitude']) and not math.isnan(row['decimalLatitude']):
        mc.add_child(Marker([row['decimalLatitude'], row['decimalLongitude']], popup=row['species']))
m.add_child(mc)

# Control de capas
folium.LayerControl().add_to(m)

# Despliegue del mapa
m
Make this Notebook Trusted to load map: File -> Trust Notebook

Mapa interactivo de calor (heatmap)

# Creación del mapa base
m = folium.Map(location=[9.6, -84.2], tiles='CartoDB dark_matter', zoom_start=8)


# Capa de ASP
folium.GeoJson(data="https://github.com/pf3311-cienciadatosgeoespaciales/2021-iii/raw/main/contenido/b/datos/asp.geojson", 
               name="ASP").add_to(m)


# Capa de calor de registros de presencia de murciélagos
HeatMap(data=murcielagos[['decimalLatitude', 'decimalLongitude']], radius=10).add_to(m)

# Control de capas
folium.LayerControl().add_to(m)

# Despliegue del mapa
m
Make this Notebook Trusted to load map: File -> Trust Notebook

Cálculo de la cantidad de especies por ASP

Conversión del dataframe de murciélagos a geodataframe

murcielagos = gpd.GeoDataFrame(murcielagos, 
                               geometry=gpd.points_from_xy(murcielagos.decimalLongitude, murcielagos.decimalLatitude))
# Join espacial de las capas de ASP y registros de presencia de murciélagos

asp_contienen_murcielagos = asp.sjoin(murcielagos, how="left", op="contains")

# Conteo de especies en cada ASP
asp_especies = asp_contienen_murcielagos.groupby("id").species.nunique()
asp_especies = asp_especies.reset_index() # para convertir la serie a dataframe

asp_especies.rename(columns = {'species': 'cantidad_especies_murcielagos'}, inplace = True)

asp_especies
/home/mfvargas/miniconda3/envs/pf3311/lib/python3.10/site-packages/IPython/core/interactiveshell.py:3457: FutureWarning: The `op` parameter is deprecated and will be removed in a future release. Please use the `predicate` parameter instead.
  exec(code_obj, self.user_global_ns, self.user_ns)
/home/mfvargas/miniconda3/envs/pf3311/lib/python3.10/site-packages/geopandas/geodataframe.py:1938: UserWarning: CRS mismatch between the CRS of left geometries and the CRS of right geometries.
Use `to_crs()` to reproject one of the input geometries to match the CRS of the other.

Left CRS: EPSG:4326
Right CRS: None

  return geopandas.sjoin(left_df=self, right_df=df, *args, **kwargs)
id cantidad_especies_murcielagos
0 areas_silvestres_protegidas.1 0
1 areas_silvestres_protegidas.10 0
2 areas_silvestres_protegidas.100 0
3 areas_silvestres_protegidas.101 2
4 areas_silvestres_protegidas.102 0
... ... ...
167 areas_silvestres_protegidas.95 1
168 areas_silvestres_protegidas.96 0
169 areas_silvestres_protegidas.97 0
170 areas_silvestres_protegidas.98 1
171 areas_silvestres_protegidas.99 0

172 rows × 2 columns

Salidas

Tabular

# Join para agregar la columna con el conteo a la capa de ASP
asp_especies = asp_especies.join(asp.set_index('id'), on='id', rsuffix='_b')

asp_especies[["nombre_asp", "cantidad_especies_murcielagos"]].sort_values("cantidad_especies_murcielagos", ascending=[False])
nombre_asp cantidad_especies_murcielagos
51 Golfo Dulce 54
25 Arenal Monteverde 31
111 Palo Verde 29
5 La Selva 27
129 Barra del Colorado 27
... ... ...
56 Humedal Laguna Madrigal 0
55 Rio Oro 0
54 Preciosa Platanares 0
53 Punta Rio Claro 0
171 Montana de El Tigre 0

172 rows × 2 columns

Gráfica

asp_especies_grafico = asp_especies[["nombre_asp", "cantidad_especies_murcielagos"]].sort_values("cantidad_especies_murcielagos", ascending=[False]).head(15)


# Graficación
asp_especies_grafico.plot(x='nombre_asp', 
                          y='cantidad_especies_murcielagos', 
                          kind='bar', 
                          figsize=(20,10), 
                          color='red')

# Título y leyendas en los ejes
plt.title('Cantidad de especies de murciélagos por ASP', fontsize=20)
plt.xlabel('ASP', fontsize=16)
plt.ylabel('Cantidad de especies', fontsize=16)
Text(0, 0.5, 'Cantidad de especies')
../../_images/ejemplo-analisis-pandas-geopandas-folium_27_1.png

Geoespacial

# Creación del mapa base
m = folium.Map(location=[9.8, -84], tiles='CartoDB positron', zoom_start=8)

folium.Choropleth(
    name="Cantidad de especies en ASP",
    geo_data=asp,
    data=asp_especies,
    columns=['id', 'cantidad_especies_murcielagos'],
    bins=8,
    key_on='feature.properties.id',
    fill_color='Reds', 
    fill_opacity=0.5, 
    line_opacity=1,
    legend_name='Cantidad de especies de murciélagos',
    smooth_factor=0).add_to(m)

# Control de capas
folium.LayerControl().add_to(m)

# Despliegue del mapa
m
Make this Notebook Trusted to load map: File -> Trust Notebook